/**
 * WebSocket管理器
 * 负责处理所有实时数据的WebSocket连接
 */
window.WebSocketManager = class WebSocketManager {
    constructor(config = {}) {
        this.config = {
            url: config.url || 'ws://localhost:8080',
            reconnectInterval: config.reconnectInterval || 3000,
            maxReconnectAttempts: config.maxReconnectAttempts || 5,
            heartbeatInterval: config.heartbeatInterval || 30000,
            debug: config.debug || true, // 默认开启调试以便于排错
            fallbackMode: config.fallbackMode || true, // 添加降级模式
            ...config
        };

        this.ws = null;
        this.reconnectAttempts = 0;
        this.heartbeatTimer = null;
        this.subscriptions = new Map();
        this.messageBuffer = [];
        this.isConnected = false;
        this.connectionPromise = null;

        // 绑定方法
        this.connect = this.connect.bind(this);
        this.reconnect = this.reconnect.bind(this);
        this.handleMessage = this.handleMessage.bind(this);
        this.handleClose = this.handleClose.bind(this);
        this.handleError = this.handleError.bind(this);
        this.startHeartbeat = this.startHeartbeat.bind(this);
        this.stopHeartbeat = this.stopHeartbeat.bind(this);
    }

    /**
     * 初始化WebSocket连接
     * @returns {Promise} 连接建立的Promise
     */
    async connect() {
        if (this.connectionPromise) {
            return this.connectionPromise;
        }

        this.connectionPromise = new Promise((resolve, reject) => {
            try {
                // 添加连接超时处理
                const connectionTimeout = setTimeout(() => {
                    this.log('WebSocket连接超时');
                    if (this.ws && this.ws.readyState !== WebSocket.OPEN) {
                        this.ws.close();
                        reject(new Error('连接超时'));
                    }
                }, 5000); // 5秒超时
                
                this.ws = new WebSocket(this.config.url);

                this.ws.onopen = () => {
                    clearTimeout(connectionTimeout);
                    this.log('WebSocket连接已建立');
                    this.isConnected = true;
                    this.reconnectAttempts = 0;
                    this.startHeartbeat();
                    this.flushMessageBuffer();
                    resolve();
                    
                    // 通知系统WebSocket已连接
                    document.dispatchEvent(new CustomEvent('websocket-connected'));
                };

                this.ws.onmessage = this.handleMessage;
                this.ws.onclose = (event) => {
                    clearTimeout(connectionTimeout);
                    this.handleClose(event);
                };
                this.ws.onerror = (error) => {
                    clearTimeout(connectionTimeout);
                    this.handleError(error);
                    reject(error);
                };
            } catch (error) {
                this.log('WebSocket连接失败:', error);
                
                if (this.config.fallbackMode) {
                    this.log('启用降级模式');
                    document.dispatchEvent(new CustomEvent('websocket-fallback', {
                        detail: { error: 'WebSocket连接失败，切换到降级模式' }
                    }));
                }
                
                reject(error);
            }
        }).catch(error => {
            this.connectionPromise = null;
            throw error;
        });

        return this.connectionPromise;
    }

    /**
     * 重新连接
     * @private
     */
    async reconnect() {
        if (this.reconnectAttempts >= this.config.maxReconnectAttempts) {
            this.log('达到最大重连次数，停止重连');
            return;
        }

        this.reconnectAttempts++;
        this.log(`尝试重新连接... (${this.reconnectAttempts}/${this.config.maxReconnectAttempts})`);

        try {
            await this.connect();
            this.log('重新连接成功');
        } catch (error) {
            this.log('重新连接失败:', error);
            setTimeout(this.reconnect, this.config.reconnectInterval);
        }
    }

    /**
     * 处理接收到的消息
     * @param {MessageEvent} event WebSocket消息事件
     * @private
     */
    handleMessage(event) {
        try {
            const message = JSON.parse(event.data);
            
            // 处理心跳响应
            if (message.type === 'heartbeat') {
                return;
            }

            // 处理订阅的消息
            if (message.topic && this.subscriptions.has(message.topic)) {
                const handlers = this.subscriptions.get(message.topic);
                handlers.forEach(handler => {
                    try {
                        handler(message.data);
                    } catch (error) {
                        this.log('消息处理器执行错误:', error);
                    }
                });
            }
        } catch (error) {
            this.log('消息解析错误:', error);
        }
    }

    /**
     * 处理连接关闭
     * @private
     */
    handleClose() {
        this.log('WebSocket连接已关闭');
        this.isConnected = false;
        this.connectionPromise = null;
        this.stopHeartbeat();

        // 尝试重新连接
        setTimeout(this.reconnect, this.config.reconnectInterval);
    }

    /**
     * 处理错误
     * @param {Event} error 错误事件
     * @private
     */
    handleError(error) {
        this.log('WebSocket错误:', error);
        
        // 如果启用了降级模式，在WebSocket连接失败时不会阻塞UI
        if (this.config.fallbackMode) {
            document.dispatchEvent(new CustomEvent('websocket-fallback', {
                detail: { error: 'WebSocket连接失败，切换到降级模式' }
            }));
        }
    }

    /**
     * 开始心跳检测
     * @private
     */
    startHeartbeat() {
        this.stopHeartbeat();
        this.heartbeatTimer = setInterval(() => {
            if (this.isConnected) {
                this.send({
                    type: 'heartbeat',
                    timestamp: Date.now()
                });
            }
        }, this.config.heartbeatInterval);
    }

    /**
     * 停止心跳检测
     * @private
     */
    stopHeartbeat() {
        if (this.heartbeatTimer) {
            clearInterval(this.heartbeatTimer);
            this.heartbeatTimer = null;
        }
    }

    /**
     * 发送消息
     * @param {Object} data 要发送的数据
     * @returns {Promise<void>}
     */
    async send(data) {
        if (!this.isConnected) {
            this.messageBuffer.push(data);
            await this.connect();
            return;
        }

        try {
            this.ws.send(JSON.stringify(data));
        } catch (error) {
            this.log('发送消息失败:', error);
            throw error;
        }
    }

    /**
     * 发送缓冲区中的消息
     * @private
     */
    flushMessageBuffer() {
        while (this.messageBuffer.length > 0) {
            const data = this.messageBuffer.shift();
            this.send(data).catch(error => {
                this.log('发送缓冲消息失败:', error);
            });
        }
    }

    /**
     * 订阅主题
     * @param {string} topic 主题名称
     * @param {Function} handler 消息处理函数
     */
    subscribe(topic, handler) {
        if (!this.subscriptions.has(topic)) {
            this.subscriptions.set(topic, new Set());
            // 向服务器发送订阅请求
            this.send({
                type: 'subscribe',
                topic
            }).catch(error => {
                this.log(`订阅主题 ${topic} 失败:`, error);
            });
        }

        this.subscriptions.get(topic).add(handler);
    }

    /**
     * 取消订阅主题
     * @param {string} topic 主题名称
     * @param {Function} handler 消息处理函数
     */
    unsubscribe(topic, handler) {
        if (this.subscriptions.has(topic)) {
            const handlers = this.subscriptions.get(topic);
            handlers.delete(handler);

            if (handlers.size === 0) {
                this.subscriptions.delete(topic);
                // 向服务器发送取消订阅请求
                this.send({
                    type: 'unsubscribe',
                    topic
                }).catch(error => {
                    this.log(`取消订阅主题 ${topic} 失败:`, error);
                });
            }
        }
    }

    /**
     * 关闭连接
     */
    close() {
        this.stopHeartbeat();
        if (this.ws) {
            this.ws.close();
        }
    }

    /**
     * 日志输出
     * @private
     */
    log(...args) {
        if (this.config.debug) {
            console.log('[WebSocketManager]', ...args);
        }
    }
}